﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using System.Runtime.Serialization.Formatters.Binary;

#endregion

namespace Neto;
/*
 https://www.cnblogs.com/MarsPanda/p/16843928.html
 *由测试得出结论:
1 首选Expression表达式树,性能大幅领先于反射,耗时仅为反射的1/70
2 反射,最常用的深度拷贝方法,书写比较简单
3 JSONConvert,最简答的写法,适用于偶尔需要深度拷贝的时候使用
4 BinaryFormatter,不推荐,需要在类上加上序列化声明,并且在.NET 5.0中该方法已经被微软声明为过期.
 *
 */

/// <summary>
///     克隆扩展
/// </summary>
public static class CloneExtension
{
    /// <summary>
    ///     使用 Expression 表达式树实现的高性能深拷贝方法【推荐方式】
    /// </summary>
    /// <typeparam name="T">需要深拷贝的对象类型</typeparam>
    /// <param name="obj">要拷贝的对象实例</param>
    /// <returns>一个新的、属性值相同的对象实例</returns>
    /// <remarks>
    ///     此方法基于表达式树生成克隆逻辑，性能远高于反射或 JSON 序列化。
    ///     适用于频繁调用、性能敏感的场景。
    /// </remarks>
    public static T ExpressionClone<T>(this T obj)
    {
        return obj == null ? obj : DeepCloneExtension<T, T>.Trans(obj);
    }
    
    /// <summary>
    ///     Json深度拷贝【速度慢】
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    [Obsolete]
    public static T? DeepCopyJson<T>(this T obj)
    {
        // 不要序列化空对象，只需返回该对象的默认值
        if (ReferenceEquals(obj, null)) return default;

        var deserializeSettings =
            new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
        var serializeSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
        return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj, serializeSettings),
            deserializeSettings);
    }

    /// <summary>
    ///     使用反射实现的深拷贝方法【适用于简单对象，性能较低】
    /// </summary>
    /// <typeparam name="T">需要深拷贝的对象类型</typeparam>
    /// <param name="obj">要拷贝的对象</param>
    /// <returns>一个新的、属性值相同的对象实例</returns>
    [Obsolete]
    public static T? DeepCopyReflection<T>(T obj)
    {
        // 如果对象为空，则返回默认值（null 或者 null 类型）
        if (obj == null) return default;

        // 获取对象的运行时类型
        var type = obj.GetType();

        // 创建目标对象的新实例
        var o = Activator.CreateInstance(type);

        // 获取所有公共属性
        var properties = type.GetProperties();

    
        foreach (var property in properties)
        {
            // 忽略索引器和非读写属性
            if (property.GetIndexParameters().Length > 0 || 
                property.GetSetMethod() == null || 
                property.GetGetMethod() == null)
                continue;

            // 获取原对象中该属性的值
            var value = property.GetValue(obj);

            // 将值设置到新对象的对应属性上
            property.SetValue(o, value);
        }

        return (T)o;
    }

   
}